/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"

#ifndef M_PI_2
#define M_PI_2 REAL(1.5707963267948966192313216916398)
#endif


#include "OpenVDB.h"

#include <节点/插座/C_数值插座.h>
#include <节点/插座/C_物体插座.h>

#include <节点/插座/list/list矢量插座.h>
#include <节点/插座/list/list数值插座.h>


#include <Range.h>



//#include <openvdb/openvdb.h>
//#include <openvdb/tools/VolumeToMesh.h>
//#include <openvdb/tools/MeshToVolume.h>
//#include <openvdb/tools/LevelSetUtil.h>
//#include <openvdb/tools/ParticlesToLevelSet.h>

#include "异步解算/物理异步解算.h"




struct S_ParticleList {
	//using PosType = openvdb::Vec3R;
	std::vector<vec3> positions;
	std::vector<float32> radii;

	size_t size() const {
		return (size_t)positions.size();
	}

	//void getPos(size_t n, openvdb::Vec3R& xyz) const {
	//	xyz = &positions[n].x;
	//}
	//
	//void getPosRad(size_t n, openvdb::Vec3R& xyz, openvdb::Real& radius) const {
	//	xyz = &positions[n].x;
	//	radius = radii[n];
	//}
};


class C_OpenVDB网格 {

	//openvdb::FloatGrid::Ptr m_网格;

public:
	C_OpenVDB网格() {
		//m_网格 = nullptr;
	}
	~C_OpenVDB网格() {
		//if (m_网格) m_网格.reset();
	}


	//std::vector<openvdb::Vec3s> out_points;
	//std::vector<openvdb::Vec4I> out_quads;
	//std::vector<openvdb::Vec3I> out_tris;


	//const openvdb::FloatGrid::Ptr& f_get网格() { return m_网格; }

	//void f_set网格(const openvdb::FloatGrid::Ptr& grid) { m_网格 = grid; }

	void f_体素到网格(std::vector<vec3>& m_Vert, std::vector<uvec3>& index, float32 等值面, float32 曲面自适应阈值, float32 三角形方向) {
		
		/*openvdb::tools::volumeToMesh<openvdb::FloatGrid>(*this->m_网格,
			out_points,
			out_tris,
			out_quads,
			等值面,
			曲面自适应阈值,
			三角形方向);*/

		
		/*int64 num = out_points.size();
		m_Vert.resize(num);
		memcpy(m_Vert.data(), out_points.data(), sizeof(vec3) * num);

		num = out_quads.size();
		index.resize(num * 2 + out_tris.size());

		if (index.size()) {
			
			auto* vdb_qi = out_quads.data();
			auto* vdb_ti = out_tris.data();
			auto* ti = index.data();
			for (int64 i = 0; i < num; ++i) {
				uint64 t_id = i * 2;
				ti[t_id].x = vdb_qi[i].x();
				ti[t_id].y = vdb_qi[i].y();
				ti[t_id].z = vdb_qi[i].z();

				ti[t_id + 1].x = ti[t_id].x;
				ti[t_id + 1].y = ti[t_id].z;
				ti[t_id + 1].z = vdb_qi[i].w();
			}

			uint64 offset = num * 2;
			num = out_tris.size();
			for (int64 i = 0; i < num; ++i) {
				ti[i + offset].x = vdb_ti[i].x();
				ti[i + offset].y = vdb_ti[i].y();
				ti[i + offset].z = vdb_ti[i].z();
			}

		}*/
		
		/*for (size_t i = 0; i < out_points.size(); i++) {
			mesh->vertices[i * 3] = out_points[i].x();
			mesh->vertices[i * 3 + 1] = out_points[i].y();
			mesh->vertices[i * 3 + 2] = out_points[i].z();
		}*/

		/*for (size_t i = 0; i < out_quads.size(); i++) {
			mesh->quads[i * 4] = out_quads[i].x();
			mesh->quads[i * 4 + 1] = out_quads[i].y();
			mesh->quads[i * 4 + 2] = out_quads[i].z();
			mesh->quads[i * 4 + 3] = out_quads[i].w();
		}

		for (size_t i = 0; i < out_tris.size(); i++) {
			mesh->triangles[i * 3] = out_tris[i].x();
			mesh->triangles[i * 3 + 1] = out_tris[i].y();
			mesh->triangles[i * 3 + 2] = out_tris[i].z();
		}*/

		/*mesh->vertices = (float*)MEM_malloc_arrayN(
		out_points.size(), 3 * sizeof(float), "openvdb remesher out verts");
		mesh->quads = (unsigned int*)MEM_malloc_arrayN(
		out_quads.size(), 4 * sizeof(unsigned int), "openvdb remesh out quads");
		mesh->triangles = NULL;
		if (out_tris.size() > 0) {
		mesh->triangles = (unsigned int*)MEM_malloc_arrayN(
		out_tris.size(), 3 * sizeof(unsigned int), "openvdb remesh out tris");
		}*/

		//mesh->totvertices = out_points.size();
		//mesh->tottriangles = out_tris.size();
		//mesh->totquads = out_quads.size();
	}

	//void mesh_to_level_set(const float* vertices, uint32* faces, uint32 totvertices, uint32 totfaces,
	//	const openvdb::math::Transform::Ptr& transform) {
		//openvdb::CoordBBox coord;
		//(*m_网格).sparseFill(coord, 1.0);
		//openvdb::tools::meshToVolume()
		/*OpenVDBLevelSet_volume_to_mesh()
		std::vector<openvdb::Vec3s> points(totvertices);
		std::vector<openvdb::Vec3I> triangles(totfaces);
		std::vector<openvdb::Vec4I> quads;
		for (unsigned int i = 0; i < totvertices; i++) {
			points[i] = openvdb::Vec3s(vertices[i * 3], vertices[i * 3 + 1], vertices[i * 3 + 2]);
		}
		for (unsigned int i = 0; i < totfaces; i++) {
			triangles[i] = openvdb::Vec3I(faces[i * 3], faces[i * 3 + 1], faces[i * 3 + 2]);
		}
		this->grid = openvdb::tools::meshToLevelSet<openvdb::FloatGrid>(
			*xform, points, triangles, quads, 1);*/
	//}

	void f_粒子转体素(std::vector<vec3>& particles, std::vector<float32>& radii, float32 半径, float32 密度) {

		/*m_网格 = openvdb::FloatGrid::create(1.0f);
		m_网格->transform().postScale({ 半径, 半径, 半径 });
		
		//openvdb::v9_0::tools::ParticlesToLevelSet
		openvdb::v9_0::tools::ParticlesToLevelSet op{ *m_网格 };

		op.setGrainSize(16);
		op.setRmin(0.0f);		//不忽略粒子
		op.setRmax(FLT_MAX);
		S_ParticleList ParticleList{ particles, radii };
		op.rasterizeSpheres(ParticleList);
		op.finalize();

		openvdb::tools::sdfToFogVolume(*m_网格);
		openvdb::tools::foreach(m_网格->beginValueOn(),
			[&](const openvdb::FloatGrid::ValueOnIter& iter) {
				iter.modifyValue([&](float& value) { value *= 密度; });
		});*/

	}


   /* void filter(OpenVDBLevelSet_FilterType filter_type,
		int width,
		float distance,
		OpenVDBLevelSet_FilterBias filter_bias);*/
   /* openvdb::FloatGrid::Ptr CSG_operation_apply(const openvdb::FloatGrid::Ptr& gridA,
		const openvdb::FloatGrid::Ptr& gridB,
		OpenVDBLevelSet_CSGOperation operation);*/
};

 
static void f_体素到网格() {

}



C_OpenVDB网格节点::C_OpenVDB网格节点(S_设备环境& ctx) : C_节点基类("OpenVDB网格节点") {
	m_Name = L"VDB网格";
	m_Ctx = ctx;
	m_是否完成计算 = true;
	
	C_插座基类* socket;
	DEF_创建VecSphere_1D_插座_I(L"点");
	DEF_创建F32插座_v1_I(L"大小");
	DEF_创建F32插座_v1_I(L"曲面自适应");

	DEF_创建网格插座_O(L"网格");


	DEF_F32插座数据(f_get输入插座(2)) = 1.0f;
	DEF_F32插座数据(f_get输入插座(3)) = 0.5f;

	m_是否异步 = f_alloc_BoolProp(nullptr, L"异步计算");
	f_prop_Bool(m_是否异步) = true;

	m_Mesh = f_surface_创建网格对象(nullptr, m_Ctx, E_网格数据枚举::e_Mesh_VULKAN);
}

C_OpenVDB网格节点::~C_OpenVDB网格节点()
{

}

bool C_OpenVDB网格节点::f_update() {
	if (f_get输入插座(1)->f_isLink()) {

		if (m_是否完成计算) {

			if (m_Vert.size()) {
				f_surface_fill顶点数据(m_Mesh, (vec3*)m_Vert.data(), m_Vert.size());
			}

			if (m_Index.size()) {
				f_surface_fill索引数据(m_Mesh, (uint32*)m_Index.data(), m_Index.size() * 3);
			}
		}


		if (m_是否完成计算) {
			m_是否完成计算 = false;

			if (f_prop_Bool(m_是否异步) && m_是否完成计算) {
				bool 是否更新 = f_NodeCtx_物理模拟线程入栈(this);
				return true;
			}
			else {
				f_异步解算();
			}
		}

	}
	else {
		f_surface_清空顶点数据(m_Mesh);
		f_surface_清空索引数据(m_Mesh);
	}

	return false;
}

void C_OpenVDB网格节点::f_异步解算()
{
	auto& 球 = *DEF_VecSphere_1D插座数据(f_get输入插座(1));
	float32 半径 = DEF_F32插座数据(f_get输入插座(2));
	float32 曲面自适应 = DEF_F32插座数据(f_get输入插座(3));


	uint32 num = 球.size();
	std::vector<vec3> points(num);
	std::vector<float32> 点半径(num);
	for (uint32 i = 0; i < num; ++i) {
		points[i] = 球[i].pos;
		点半径[i] = 球[i].radius;
	}

	if (points.size()) {
		C_OpenVDB网格 vdb;

		std::vector<float32> 粒子半径;
		if (点半径.size() < points.size()) {
			粒子半径 = f_range(points.size(), 点半径.at(0));
		}
		else {
			粒子半径 = 点半径;
		}
		
		vdb.f_粒子转体素(points, 粒子半径, 半径, 1.0);
		vdb.f_体素到网格(m_Vert, m_Index, 0.1, 曲面自适应, 0.1);
	}
	else {
		//f_surface_清空顶点数据(mesh.m_GPU网格);
		//f_surface_清空索引数据(mesh.m_GPU网格);
	}

	m_是否完成计算 = true;
}

C_节点基类* f_node_载入OpenVDB网格节点(S_设备环境& ctx, FILE* f)
{
	C_OpenVDB网格节点* node = new C_OpenVDB网格节点(ctx);

	return node;
}

void f_node_保存OpenVDB网格节点(C_节点基类* n, FILE* f)
{
	C_OpenVDB网格节点* node = dynamic_cast<C_OpenVDB网格节点*>(n);

}

















